//package com.yupi.project.filters;
//
//import com.baomidou.mybatisplus.core.toolkit.StringUtils;
//import com.yupi.yuapicommon.model.entity.InterfaceInfo;
//import com.yupi.yuapicommon.model.entity.User;
//import com.yupi.yuapicommon.service.InnerInterfaceInfoService;
//import com.yupi.yuapicommon.service.InnerUserInterfaceInfoService;
//import com.yupi.yuapicommon.service.InnerUserService;
//import lombok.extern.slf4j.Slf4j;
//import org.apache.dubbo.config.annotation.DubboReference;
//import org.reactivestreams.Publisher;
//import org.springframework.cloud.gateway.filter.GatewayFilterChain;
//import org.springframework.cloud.gateway.filter.GlobalFilter;
//import org.springframework.core.Ordered;
//import org.springframework.core.io.buffer.DataBuffer;
//import org.springframework.core.io.buffer.DataBufferFactory;
//import org.springframework.core.io.buffer.DataBufferUtils;
//import org.springframework.http.HttpHeaders;
//import org.springframework.http.HttpStatus;
//import org.springframework.http.server.reactive.ServerHttpRequest;
//import org.springframework.http.server.reactive.ServerHttpResponse;
//import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
//import org.springframework.stereotype.Component;
//import org.springframework.web.server.ServerWebExchange;
//import reactor.core.publisher.Flux;
//import reactor.core.publisher.Mono;
//
//import java.net.InetSocketAddress;
//import java.nio.charset.StandardCharsets;
//import java.util.*;
//
//import static com.yupi.yuapicommon.utils.SignUtils.getSign;
//
//
///** @description 全局过滤，实现了统一日志处理、黑白名单、用户鉴权、请求重放检验、请求时间有效性、统计调用次数
//* @return
//* @author zzousrce
//* @date 2023/1/16 0:57
//*/
//@Slf4j(topic = "GatewayGlobalFilter")
//@Component
//public class GatewayGlobalFilter implements GlobalFilter, Ordered {
//
//    @DubboReference
//    private InnerUserInterfaceInfoService innerUserInterfaceInfoService;
//
//    @DubboReference
//    private InnerUserService innerUserService;
//
//    @DubboReference
//    private InnerInterfaceInfoService innerInterfaceInfoService;
//
//    private List<String> IS_BLACK = Arrays.asList();
//
//    @Override
//    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//        //1.用户发送请求到 API 网关
//        //2.请求日志
//        ServerHttpRequest request = exchange.getRequest();
//        ServerHttpResponse response = exchange.getResponse();
//        HttpHeaders headers = request.getHeaders();
//        String id = request.getId();
//        String path = request.getURI().toString();
//        String method = request.getMethod().name();
//        InetSocketAddress remoteAddress = request.getRemoteAddress();
//        InetSocketAddress localAddress = request.getLocalAddress();
//
//        log.info("请求头是：" + headers);
//        log.info("发送id是：" + id);
//        log.info("请求路径是:" + path);
//        log.info("请求IP源地址是：" + remoteAddress.getAddress());
//        log.info("请求IP目标地址是：" + localAddress.getHostString());
//        log.info("请求方法是：" + method);
//        //3.(黑白名单)
//        if(IS_BLACK.contains(localAddress.getHostString())){
//            return handleInvokeError(response, "IP在黑名单内");
//        }
//        //4.用户鉴权 (判断 ak、sk 是否合法)
//        String accessKey = headers.getFirst("accessKey");
//        String nonce = headers.getFirst("nonce");
//        String timestamp = headers.getFirst("timestamp");
//        String sign = headers.getFirst("sign");
//        User invokeUser = innerUserService.getInvokeUser(accessKey);
//        int index = path.indexOf("?");
//        InterfaceInfo interfaceInfo = innerInterfaceInfoService.getInterfaceInfo(path.substring(0,  index == -1 ? path.length() : index), method);
//        //时间戳相差不大于5分钟
//        long currentTime = System.currentTimeMillis() / 1000;
//        final long FIVE_MINUTES = 5 * 6000L;
//        if(timestamp == null || currentTime - Long.parseLong(timestamp) > FIVE_MINUTES){
//            return handleInvokeError(response, "请求时间戳过期");
//        }
//        Map<String, String> hashMap = new HashMap<>(4);
//        hashMap.put("accessKey",accessKey);
//        hashMap.put("timestamp",timestamp);
//        hashMap.put("nonce",nonce);
////        //TODO：没有解决中文乱码问题
////        hashMap.put("body",body);
//        //secretKey从数据库中拿出
//        String secretKey = invokeUser.getSecretKey();
//        String serverSign = getSign(hashMap, secretKey);
//        // 签名认证
//        if(StringUtils.isBlank(sign) || !sign.equals(serverSign)){
//            return handleInvokeError(response, "没有权限");
//        }
//        // 判断用户是否有充足的羊毛积分 能够调用该接口
//        if(invokeUser.getWoolLeft() < interfaceInfo.getWoolUsed()){
//            return handleInvokeError(response, "羊毛积分不足");
//        }
//        // 抛弃的版本
////        // 判断用户是否还有剩余调用次数
////        UserInterfaceInfo userInterfaceInfo = null;
////        try {
////            userInterfaceInfo = innerUserInterfaceInfoService.getUserInterfaceInfo(interfaceInfo.getId(), invokeUser.getId());
////        } catch (Exception e) {
////            log.error("getUserInterfaceInfo error", e);
////        }
////        if(userInterfaceInfo == null){
////            return handleInvokeError(response);
////        }
////        // 调用次数不足
////        if(userInterfaceInfo.getLeftNum() <= 0){
////            throw new BusinessException(ErrorCode.OPERATION_ERROR, "用户接口调用次数不足");
////        }
//        //6.请求转发，调用模拟接口
//        // 走完过滤器之后，才会调用远程接口，相当于异步调用，这不是我们想要的流程！
////        Mono<Void> filter = chain.filter(exchange);
//        // 7.调用模拟接口 + 响应日志
//        return handleResponse(exchange, chain, interfaceInfo, invokeUser);
//    }
//
//    /**
//     * 处理响应
//     *
//     * @param exchange
//     * @param chain
//     * @return
//     */
//    public Mono<Void> handleResponse(ServerWebExchange exchange, GatewayFilterChain chain, InterfaceInfo interfaceInfo, User user) {
//        try {
//            ServerHttpResponse originalResponse = exchange.getResponse();
//            // 缓存数据的工厂
//            DataBufferFactory bufferFactory = originalResponse.bufferFactory();
//            // 拿到响应码
//            HttpStatus statusCode = originalResponse.getStatusCode();
//            if (statusCode == HttpStatus.OK) {
//                // 装饰，增强能力
//                ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) {
//                    // 等调用完转发的接口后才会执行
//                    @Override
//                    public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
//                        log.info("body instanceof Flux: {}", (body instanceof Flux));
//                        if (body instanceof Flux) {
//                            // 7. 调用成功，接口调用次数 + 1 invokeCount，扣除用户羊毛积分
//                            try {
//                                innerUserInterfaceInfoService.invokeCount(interfaceInfo.getId(), user.getId());
//                                innerUserService.consumeWool(interfaceInfo.getWoolUsed(), user.getWoolLeft(), user.getId());
//                            } catch (Exception e) {
//                                log.error("invokeCount error" + e);
//                            }
//
//                            Flux<? extends DataBuffer> fluxBody = Flux.from(body);
//                            // 往返回值里写数据
//                            // 拼接字符串
//                            return super.writeWith(
//                                    fluxBody.map(dataBuffer -> {
//                                        byte[] content = new byte[dataBuffer.readableByteCount()];
//                                        dataBuffer.read(content);
//                                        DataBufferUtils.release(dataBuffer);//释放掉内存
//                                        // 构建日志
//                                        StringBuilder sb2 = new StringBuilder(200);
//                                        List<Object> rspArgs = new ArrayList<>();
//                                        rspArgs.add(originalResponse.getStatusCode());
//                                        String data = new String(content, StandardCharsets.UTF_8); //data
//                                        sb2.append(data);
//                                        // 打印日志
//                                        log.info("响应结果：" + data);
//                                        return bufferFactory.wrap(content);
//                                    }));
//                        } else {
//                            // 8. 调用失败，返回一个规范的错误码
//                            log.error("<--- {} 响应code异常", getStatusCode());
//                        }
//                        return super.writeWith(body);
//                    }
//                };
//                // 设置 response 对象为装饰过的
//                return chain.filter(exchange.mutate().response(decoratedResponse).build());
//            }
//            return chain.filter(exchange); // 降级处理返回数据
//        } catch (Exception e) {
//            log.error("网关处理响应异常" + e);
//            return chain.filter(exchange);
//        }
//    }
//
//
//    @Override
//    public int getOrder() {
//        return -2;
//    }
//
//    private Mono<Void> handleInvokeError(ServerHttpResponse response, String errorMessage){
//        return Mono.error(new RuntimeException(errorMessage));
//    }
//}
//
